package cn.sh.basic.service.impl;

import cn.sh.basic.domain.dto.SendSmsDto;
import cn.sh.basic.domain.dto.SendEmailDto;
import cn.sh.basic.exception.CustomException;
import cn.sh.basic.service.IVerifyCodeService;
import cn.sh.basic.util.StrUtils;
import cn.sh.basic.util.VerifyCodeUtils;
import cn.sh.user.domain.User;
import cn.sh.user.mapper.LogininfoMapper;
import cn.sh.user.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.concurrent.TimeUnit;

@Service
public class VerifyCodeServiceImpl implements IVerifyCodeService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private LogininfoMapper logininfoMapper;

    @Autowired
    private JavaMailSender javaMailSender;

    @Override
    public Object imageCode(String key) {
        //生成4位随机字符
        String code = StrUtils.getComplexRandomString(4);
        //存储redis，使用前端传来的key作为redis的key
        redisTemplate.opsForValue().set(key, code, 5, TimeUnit.MINUTES);
        //根据Code生成BASE64转码后的图片
        String base = VerifyCodeUtils.VerifyCode(110, 38, code);
        return base;
    }

    @Override
    public void sendSmsCode(SendSmsDto dto) {
        //       1. 空参数校验
        if (StringUtils.isEmpty(dto.getMobile())) {
            throw new CustomException("手机号不能为空");
        }
//        2. 判断该手机号用户是否已经注册
        User user = userMapper.queryByUserName(dto.getMobile());
        //1. 如果注册过就返回自定义异常
        if (user != null) {
            throw new CustomException("该用户已注册！");
        }
//        3. 根据前端传递过来的图片验证码的key，去redis中获取
        Object imageCode = redisTemplate.opsForValue().get(dto.getImageCodeKey());
//        1. 获取不到，返回自定义异常，图片验证码失效
        if (imageCode == null) {
            throw new CustomException("图片验证码已失效！");
        }
//        4. 判断前端填写的图片验证码与redis中获取的是否一致
        if (!imageCode.toString().equalsIgnoreCase(dto.getImageCode())) {
            //        1. 不一致，返回自定义异常，验证码不正确
            throw new CustomException("图片验证码错误！");
        }
//        5. 根据前端传递的手机号，拼接业务键去redis中查询
        String smsKey = dto.getMobile() + ":register";
        Object smsCode = redisTemplate.opsForValue().get(smsKey);

        //定义一个公共的变量作为最终发送的验证码
        String resultCode = "";
//        1. 查询到有数据
        if (smsCode != null) {
            //获取已经存在的短信验证码的时间戳
            String timeStamp = smsCode.toString().split(":")[1];
            //判断时间戳是否超过了1分钟重发时间
            if ((System.currentTimeMillis() - Long.parseLong(timeStamp)) <= 1 * 60 * 1000) {
                throw new CustomException("请勿重复发送短信验证码！");
            }
            //没超过就更新redis的过期时间
            redisTemplate.opsForValue().set(smsKey, smsCode, 3, TimeUnit.MINUTES);
            //准备发送老的验证码
            resultCode = smsCode.toString().split(":")[0];
        } else {
            //生成要发送的验证码
            String newSmsCode = StrUtils.getComplexRandomString(4);
            //生成要保存redis的value值
            String redisValueCode = newSmsCode + ":" + System.currentTimeMillis();
            //保存到redis中，添加过期时间
            redisTemplate.opsForValue().set(smsKey, redisValueCode, 3, TimeUnit.MINUTES);
            //准备发送新的验证码
            resultCode = newSmsCode;
        }
        //发送验证码
        //SmsUtils.sendSms(dto.getMobile(),"您好，您的验证码是:"+resultCode);
        System.out.println("您好，您的验证码是:" + resultCode);
    }

    @Override
    public void sendEmailCode(SendEmailDto mailDto) {
        //空参数校验
        if(StringUtils.isEmpty(mailDto.getMobile())){
            throw new CustomException("邮箱号不能为空!");
        }
        //判断邮箱号是否已经注册
        User user = userMapper.queryByEmail(mailDto.getMobile());
        //手机号已经注册
        if(user !=null){
            throw new CustomException("用户已注册！");
        }
        //获取前端传递过来的图片验证码的key  并且去Redis中去获取
        Object imageCode = redisTemplate.opsForValue().get(mailDto.getImageCodeKey());
        //获取不到code
        if(imageCode == null){
            throw new CustomException("图片验证码已失效！");
        }
        //判断前端填写的验证码是否正确
        if(!imageCode.toString().equalsIgnoreCase(mailDto.getImageCode())){
            throw new CustomException("图片验证码填写错误！");
        }
        //把传递的邮箱号和业务键作为key
        String emailKey = mailDto.getMobile()+":register";
        //到Redis中去查询
        Object emailCode = redisTemplate.opsForValue().get(emailKey);
        //定义一个公共的变量作为最终发送的验证码
        String resultCode = "";
        //查询不为空
        if(emailCode != null){
            //获取时间戳
            String timeStamp = emailCode.toString().split(":")[1];
            //判断请求发送的短信是否超过1分钟
            if(System.currentTimeMillis() - Long.parseLong(timeStamp) <= 1*60*1000){
                //小于1分钟
                throw new CustomException("请勿重复发送邮箱验证码！");
            }else {
                //超过1分钟 刷新过期时间3分钟
                redisTemplate.opsForValue().set(emailKey,emailCode,3,TimeUnit.MINUTES);
                //发送旧的验证码
                resultCode = emailCode.toString().split(":")[0];
            }
        }else {
            //使用StrUtils工具产生4位随机码
            String newEmailCode = StrUtils.getComplexRandomString(4);
            //随机码拼接时间戳
            String newSmsCodeValue = newEmailCode+":"+ System.currentTimeMillis();
            //存储到Redis 并且设置过期时间3分钟
            redisTemplate.opsForValue().set(emailKey,newSmsCodeValue,3,TimeUnit.MINUTES);
            //发送验证码
            resultCode = newEmailCode;
        }
        SimpleMailMessage msg = new SimpleMailMessage();
        //设置发送人
        //msg.setFrom(发送邮件人);
        msg.setFrom("1589867195@qq.com");
        //邮件主题
        msg.setSubject("用户注册");
        //邮件内容
        msg.setText("您好，您的验证码是:"+resultCode);
        //收件人
        //msg.setTo(sendEmailDto.getEmail());
        msg.setTo("1589867195@qq.com");
        //发送邮件
        javaMailSender.send(msg);
    }
}
